﻿using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Text.RegularExpressions;

namespace Eswat.Razor
{
	/// <summary>
	/// Test runner for Razor language files.
	/// </summary>
	public class RazorTestRunner : TestRunnerBase<string>
	{
		// HACK: force the DLR assembly to load dynamic in the AppDomain for Razor
		private dynamic _hereToMakeSureToLoadDynamicIntoTheAppDomainForRazorEngineToUseIt = 0;

		private Regex _include = new Regex("^@include \"[a-zA-Z0-9_-]+([.][a-zA-Z0-9_-]+)*[.]dll\"\\s*$", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.Multiline);

		/// <summary>
		/// Called when [before test].
		/// </summary>
		/// <typeparam name="TTestContext">The type of the test context.</typeparam>
		/// <param name="testContext">The test context.</param>
		/// <param name="availableInMemoryAssemblies">The available in memory assemblies.</param>
		protected override void OnBeforeTest<TTestContext>(
			ITestContext<TTestContext> testContext,
			IEnumerable<Assembly> availableInMemoryAssemblies)
		{
			var includes = _include.Matches(testContext.Template);

			foreach (Match include in includes)
			{
				var includeValue = include.Value.Replace("@include ", string.Empty).Replace("\"", string.Empty).Trim();

				var path = Path.GetFullPath(includeValue);

				Assembly.LoadFile(path);
			}
		}

		/// <summary>
		/// Runs the test.
		/// </summary>
		/// <typeparam name="TTestContext">The type of the test context.</typeparam>
		/// <param name="testContext">The test context.</param>
		/// <returns>
		/// The test result.
		/// </returns>
		protected override string RunTest<TTestContext>(ITestContext<TTestContext> testContext)
		{
			var content = this._include.Replace(testContext.Template, string.Empty);

			// HACK: Simple way to avoid compile warning for unused field.
			this._hereToMakeSureToLoadDynamicIntoTheAppDomainForRazorEngineToUseIt++;

			RazorEngine.Razor.SetTemplateBase(typeof(RazorTestTemplate<>));

			var parseResult = RazorEngine.Razor.Parse(content, testContext.Target);

			return parseResult;
		}
	}
}
